package cn.shadow.utils;

import com.google.common.io.BaseEncoding;

public class IDUtils {

    public static final int MAX_OPERATOR_ID = (1 << 8) - 1; // 8 bit
    public static final int MAX_SERVER_ID = (1 << 13) - 1; // 13 bit
    private static final BaseEncoding encoding = BaseEncoding.base64Url();

    private IDUtils() {
    }

    public static String newEventID(int operatorID, int serverID, int operateType,
            int timeSeconds) {
        return newEventID(operatorID << 13 | serverID, operateType, timeSeconds);
    }

    public static String newEventID(int combineOperatorIDAndServerID, int operateType,
            int timeSeconds) {
        // eventID生成，8bit 运营商+13bit 区服+10bit 操作类型+bit 随机数

        byte[] bytes = new byte[12];

        int low = (int) (Math.random()*(Integer.MAX_VALUE));
        int mid = (operateType << 21) | combineOperatorIDAndServerID;

        int2bytes(low, bytes, 0);
        int2bytes(mid, bytes, 4);
        int2bytes(timeSeconds, bytes, 8);

        return encoding.encode(bytes);
    }

    public static String encodeBase64(byte[] bytes) {
        return encoding.encode(bytes);
    }

    public static byte[] decodeBase64(String s) {
        return encoding.decode(s);
    }

    public static void int2bytes(int value, byte[] bytes, int offset) {
        for (int i = 0; i < 4; i++) {
            bytes[offset++] = (byte) ((value >> (8 * i)) & 0xFF);
        }
    }

    public static int bytes2Int(byte[] bytes, int offset) {
        int n = 0;
        for (int i = 0; i < 4; i++) {
            n |= (bytes[offset++] & 0xFF) << (8 * i);
        }

        return n;
    }

    public static long bytes2Long(byte[] bytes, int offset) {
        long n = 0;
        for (int i = 0; i < 8; i++) {
            n |= (bytes[offset++] & 0xFFL) << (8 * i);
        }

        return n;
    }

    public static long combineUserAndServerAndOperatorID(int userID, int serverID, int operatorID) {
        return Utils.int2Long(combineOperatorAndServerID(operatorID, serverID), userID);
    }

    public static long combineUserAndServerAndOperatorID(int userID,
                                                         int combineOperatorAndServerID) {
        return Utils.int2Long(combineOperatorAndServerID, userID);
    }

    public static int getUserID(long combine) {
        return (int) combine;
    }

    public static int getCombinedServerAndOperatorID(long combine) {
        return (int) (combine >>> 32);
    }

    public static int getServerID(long combine) {
        return ((int) (combine >>> 32)) & MAX_SERVER_ID;
    }

    public static int getOperatorID(long combine) {
        return (int) (combine >>> 45);
    }

    public static int combineOperatorAndServerID(int operatorID, int serverID) {
        return ((operatorID << 13) | serverID);
    }

    public static int getOperatorIDFromCombineOperatorAndServerID(int com) {
        return com >>> 13;
    }

    public static int getServerIDFromCombineOperatorAndServerID(int com) {
        return com & MAX_SERVER_ID;
    }



}
